<html>
<head><meta charset="utf-8"><title>validity of unions · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html">validity of unions</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="168600031"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168600031" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168600031">(Jun 20 2019 at 14:23)</a>:</h4>
<p><a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/73" target="_blank" title="https://github.com/rust-lang/unsafe-code-guidelines/issues/73">https://github.com/rust-lang/unsafe-code-guidelines/issues/73</a></p>
<p>Could we allow <code>Option&lt;MaybeUninit&lt;T&gt;&gt;</code> to have the same size as <code>MaybeUninit&lt;T&gt;</code> ?</p>
<p>This case appears to me to be much simpler than layout optimizations for unions in general, yet I am not sure how we could ever allow that.</p>



<a name="168600050"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168600050" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168600050">(Jun 20 2019 at 14:23)</a>:</h4>
<p>Consider unions that could be <code>repr(transparent)</code> (but don't necessarily need to be), that is, unions with a single non-zero-sized field. These unions do always have valid fields because, independently of the bytes of the union, all zero-sized fields are always valid. </p>
<p>The non-zero-sized field is, however, not always valid, and we want to support that to support partial initialization.</p>



<a name="168600304"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168600304" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168600304">(Jun 20 2019 at 14:26)</a>:</h4>
<p>For example,</p>
<div class="codehilite"><pre><span></span><span class="k">union</span> <span class="nc">U</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">a</span>: <span class="p">(),</span><span class="w"> </span><span class="n">b</span>: <span class="nc">NonNull</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">U</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">a</span>: <span class="p">()</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// U::b == undef</span>
<span class="kd">let</span><span class="w"> </span><span class="n">opt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">u</span><span class="p">);</span><span class="w"> </span><span class="c1">// ??</span>
<span class="kd">let</span><span class="w"> </span><span class="n">opt</span>: <span class="nb">Option</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">transmute</span><span class="p">(</span><span class="n">u</span><span class="p">);</span><span class="w"> </span><span class="c1">// ??</span>
</pre></div>



<a name="168600441"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168600441" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168600441">(Jun 20 2019 at 14:28)</a>:</h4>
<p>So even though <code>NonNull&lt;T&gt;</code> has a niche, when constructing an <code>Option&lt;U&gt;</code>, we would need extra requirements about the contents of the niche, even though the union has a valid field (<code>U::a</code>).</p>



<a name="168600484"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168600484" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168600484">(Jun 20 2019 at 14:28)</a>:</h4>
<p>We would at least have to require that the niche is always "valid" (whatever that might mean).</p>



<a name="168600657"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168600657" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168600657">(Jun 20 2019 at 14:30)</a>:</h4>
<p>That means that this would be ok:</p>
<div class="codehilite"><pre><span></span><span class="kd">let</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MaybeUninit</span>::<span class="o">&lt;</span><span class="n">NonNull</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;&gt;</span>::<span class="n">zeroed</span><span class="p">();</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">opt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">u</span><span class="p">);</span><span class="w">  </span><span class="c1">// niche is &quot;valid&quot;</span>
</pre></div>


<p>but this wouldn't:</p>
<div class="codehilite"><pre><span></span><span class="kd">let</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MaybeUninit</span>::<span class="o">&lt;</span><span class="n">NonNull</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;&gt;</span>::<span class="n">uninitialized</span><span class="p">();</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">opt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">u</span><span class="p">);</span><span class="w">  </span><span class="c1">// niche is &quot;invalid&quot;</span>
</pre></div>



<a name="168601191"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168601191" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168601191">(Jun 20 2019 at 14:36)</a>:</h4>
<p>AFAICT this means that we wouldn't only have to require that the union has at least one valid field to perform niche optimizations, but also that all fields "share" at least one niche. E.g., if we had:</p>
<div class="codehilite"><pre><span></span><span class="k">union</span> <span class="nc">U</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">a</span>: <span class="nc">NonNull</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="n">b</span>: <span class="kp">&amp;</span><span class="nb">&#39;static</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</pre></div>


<p>then I think we could make <code>Option&lt;U&gt;</code> and <code>U</code> have the same size.</p>



<a name="168601853"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168601853" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168601853">(Jun 20 2019 at 14:44)</a>:</h4>
<blockquote>
<p>Could we allow Option&lt;MaybeUninit&lt;T&gt;&gt; to have the same size as MaybeUninit&lt;T&gt; ?</p>
</blockquote>
<p>given the goals of <code>MaybeUninit</code> I think that is impossible</p>



<a name="168601881"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168601881" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168601881">(Jun 20 2019 at 14:44)</a>:</h4>
<blockquote>
<p>we wouldn't only have to require that the union has at least one valid field to perform niche optimizations, but also that all fields "share" at least one niche</p>
</blockquote>
<p>yes</p>



<a name="168601891"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168601891" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168601891">(Jun 20 2019 at 14:44)</a>:</h4>
<p>but I still think we shouldn't</p>



<a name="168602298"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602298" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602298">(Jun 20 2019 at 14:49)</a>:</h4>
<p><span class="user-mention" data-user-id="120791">@RalfJ</span> adding a ZST field to an union would have big consequences from a point-of-view of layout optimizations</p>



<a name="168602315"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602315" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602315">(Jun 20 2019 at 14:49)</a>:</h4>
<p>that feels brittle</p>



<a name="168602405"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602405" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602405">(Jun 20 2019 at 14:50)</a>:</h4>
<p>anyways, your <code>Mix</code> example here: <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/73#issuecomment-460572178" target="_blank" title="https://github.com/rust-lang/unsafe-code-guidelines/issues/73#issuecomment-460572178">https://github.com/rust-lang/unsafe-code-guidelines/issues/73#issuecomment-460572178</a> is not optimizable AFAICT</p>



<a name="168602427"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602427" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602427">(Jun 20 2019 at 14:50)</a>:</h4>
<p>the fields there do not share a niche</p>



<a name="168602490"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602490" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602490">(Jun 20 2019 at 14:51)</a>:</h4>
<p>absolutely, that's why I brought it up</p>



<a name="168602602"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602602" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602602">(Jun 20 2019 at 14:52)</a>:</h4>
<p>I have spelled out the ivnariant that we might use somewhere, and it's basically what you are suggesting here</p>



<a name="168602637"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602637" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602637">(Jun 20 2019 at 14:52)</a>:</h4>
<p>is that summarized somewhere ?</p>



<a name="168602641"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602641" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602641">(Jun 20 2019 at 14:52)</a>:</h4>
<p>"for bit/byte at position i of the union, that bit/byte is allowed to have value v if any variant of the union allows the bit/byte at index i to have value v"</p>



<a name="168602675"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602675" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602675">(Jun 20 2019 at 14:53)</a>:</h4>
<p>but I think this is an awful invariant. it is too complicated, it is crazy to check for at run-time, the benefit is too minimal IMO</p>



<a name="168602683"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602683" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602683">(Jun 20 2019 at 14:53)</a>:</h4>
<p>i think we can at least write down the validity invariant for unions that do not share a niche</p>



<a name="168602759"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602759" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602759">(Jun 20 2019 at 14:54)</a>:</h4>
<p>well I think we all agree that if there is a field <code>()</code>, then the union may contain any data</p>



<a name="168602779"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602779" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602779">(Jun 20 2019 at 14:54)</a>:</h4>
<p>yes</p>



<a name="168602796"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168602796" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168602796">(Jun 20 2019 at 14:54)</a>:</h4>
<p>niche as a notion is <em>derived from</em> validity invariant, so defining validity in terms of niche is a bit cyclic ;)</p>



<a name="168603291"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168603291" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168603291">(Jun 20 2019 at 15:00)</a>:</h4>
<p>I thought niche was being moved to layout, maybe ?</p>



<a name="168603325"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity%20of%20unions/near/168603325" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/validity.20of.20unions.html#168603325">(Jun 20 2019 at 15:00)</a>:</h4>
<p>I can't remember, there was an issue about that somewhere</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>